package com.my.study.aspect;

import com.alibaba.fastjson.JSON;
import com.my.study.aop.anntation.OperationLog;
import com.my.study.config.EmailConfig;
import com.my.study.dto.OperateLogDTO;
import com.my.study.exception.BusinessException;
import com.my.study.service.OperateLogService;
import com.my.study.utils.IpUtils;
import com.my.study.utils.SendEmailUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.core.util.UuidUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.Order;
import org.springframework.mail.MailSender;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;

/**
 * 日志切面类
 */
@Aspect
@Component
@Slf4j
@Order(2)
@ConditionalOnProperty(prefix = "operation", name = "enable", havingValue = "true")
public class OperationLogAspect {

    @Autowired
    private EmailConfig emailConfig;
    @Autowired
    private MailSender mailSender;
    @Autowired
    private OperateLogService operateLogService;


    @Before("@annotation(operationLog)")
    public void doBefore(JoinPoint joinPoint, OperationLog operationLog) {
        // 获取请求对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 获取数据
        OperateLogDTO operateLog = getOperateLog(joinPoint, operationLog, request);
        operateLogService.addOperateLog(operateLog);
    }

    /**
     * 获取对象数据
     *
     * @param joinPoint
     * @param operationLog
     * @param request
     * @return
     */
    private OperateLogDTO getOperateLog(JoinPoint joinPoint, OperationLog operationLog, HttpServletRequest request) {
        // 封装数据
        OperateLogDTO operateLog = new OperateLogDTO();
        operateLog.setContent(operationLog.operationContent());
        Object[] args = joinPoint.getArgs();
        operateLog.setContentJson(JSON.toJSONString(args));
        operateLog.setCreateTime(new Date());
        operateLog.setIp(IpUtils.getIpAddress(request));
        operateLog.setId(UuidUtil.getTimeBasedUuid().toString().replaceAll("-",""));
        operateLog.setSysUserId(request.getHeader("userId"));
        return operateLog;
    }

    /**
     * 发送邮件通知
     *
     * @param exception
     */
    @AfterThrowing(value = "@annotation(operationLog)", throwing = "exception")
    public void doAfterError(Exception exception, OperationLog operationLog) {
        try {
            // 业务异常无需通知
            if(exception instanceof BusinessException){
                return;
            }
            String ip = InetAddress.getLocalHost().getHostAddress();
            log.info("当前服务器" + ip + "执行异常" + exception);
            //发送邮件通知开发人员
            String title = "服务器执行异常";
            String text = "尊敬的开发人员,您好:\n"
                    + "\n本次本次应服务器执行发生异常，服务器IP为:" + ip + ",请及时登录，排查问题（请勿泄露服务器IP）\n"
                    + "\n(这是一封自动发送的邮件，请不要直接回复）";
            SendEmailUtil.getInstance(emailConfig, mailSender).sendEmail(title, text);
        } catch (UnknownHostException e) {
            log.info("获取当前服务器IP发生异常" + e.getMessage());
        }
    }
}